#include <vector>
#include "AdminRightManager.h"
#include "AdminConfiguration.h"
#include "AdminChannelRight.h"
#include "AdminHostRight.h"

AgoraAdmin::IRightManager*	AgoraAdmin::RightManager::_instance = NULL;

AgoraAdmin::RightManager::RightManager()
{
}

AgoraAdmin::IRightManager*	AgoraAdmin::RightManager::GetRightManager()
{
	if (RightManager::_instance == NULL)
		RightManager::_instance = new RightManager();
	return RightManager::_instance;
}

const IChannelRight&		AgoraAdmin::RightManager::GetChannelRight(IUser* user, IChannel* channel)
{
	if(this->_userChannelRight.count(user) && this->_userChannelRight[user].count(channel))
		return *(this->_userChannelRight[user][channel]);
	IDatabase::DbResult* result = Configuration::GetConfiguration()->GetDatabase()->SelectChannelRight(user->GetId(), channel->GetId());
	if (result->size() == 0)
	{
		//creer un nouveau channelright base sur celui par default
		delete result;
		Configuration::GetConfiguration()->GetDatabase()->CreateChannelRightDefault(user->GetId(), channel->GetId());
		result = Configuration::GetConfiguration()->GetDatabase()->SelectChannelRight(user->GetId(), channel->GetId());
	}
	std::vector<bool> vectorRight;
	vectorRight.push_back((*result->at(0))["canCreate"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canDelete"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canEdit"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canEditUser"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canTalk"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canWrite"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canKick"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canBan"]->GetValueBool());
	ChannelRight* right = new ChannelRight((*result->at(0))["id"]->GetValueInt(), vectorRight);
	delete result;
	this->_userChannelRight[user][channel] = right;
	return *right;
}

void		AgoraAdmin::RightManager::SetChannelRight(IUser* user, IChannel* channel, const bool canCreate, const bool canDelete, const bool canEdit, const bool canEditUser, const bool canTalk, const bool canWrite, const bool canKick, const bool canBan)
{
	// modif map si donnee existante dans map, et la db en meme tps
	if(this->_userChannelRight.count(user) && this->_userChannelRight[user].count(channel))
		this->_userChannelRight[user][channel]->SetChannelRight(canCreate, canDelete, canEdit, canEditUser, canTalk, canWrite, canKick, canBan);
	else
	{
		// sinon on modif seulement dans la base
		unsigned int id = Configuration::GetConfiguration()->GetDatabase()->SelectChannelRightId(user->GetId(), channel->GetId());
		//ici on peut check si une erreur a ete emise, si c'est le cas on cree un right par default
		Configuration::GetConfiguration()->GetDatabase()->UpdateChannelRight(id, canCreate, canDelete, canEdit, canEditUser, canTalk, canWrite, canKick, canBan);
	}
}

void	AgoraAdmin::RightManager::RemoveChannelRight(IUser* user, IChannel* channel)
{
	// remove de la base le channel right d'un user
	Configuration::GetConfiguration()->GetDatabase()->DeleteChannelRight(user->GetId(), channel->GetId());
	if (this->_userChannelRight.count(user) && this->_userChannelRight[user].count(channel))
	{
		delete this->_userChannelRight[user][channel];
		this->_userChannelRight[user].erase(channel);
	}
}

void	AgoraAdmin::RightManager::RemoveChannelRight(IChannel* channel)
{
	// remove de la base tout les channelRights d'un channel
	Configuration::GetConfiguration()->GetDatabase()->DeleteChannelRightChannel(channel->GetId());
	std::list<IChannel*>::iterator	iteC = channel->GetChannelChild().begin();
	std::list<IChannel*>::iterator	iteE = channel->GetChannelChild().end();
	while (iteC != iteE)
	{
		this->RemoveChannelRight(*iteC);
		++iteC;
	}
	
	
	
	
	std::map<IUser*, std::map<IChannel*, IChannelRight*> >::iterator	iteCurrent = this->_userChannelRight.begin();
	std::map<IUser*, std::map<IChannel*, IChannelRight*> >::iterator	iteEnd = this->_userChannelRight.end();
	while (iteCurrent != iteEnd)
	{
		delete (*iteCurrent).second[channel];
		(*iteCurrent).second.erase(channel);
/*		std::map<IChannel*, IChanelRight*>::iterator iteDeb = (*iteCurrent).second.begin();
		std::map<IChannel*, IChanelRight*>::iterator iteFin = (*iteCurrent).second.end();
		while (iteDeb != iteFin)
		{
			if (ite
		delete (*iteCurrent).second.begin()->second;
		(*iteCurrent).second.erase(channel);
			++iteDeb;
		}*/
		++iteCurrent;
	}
}

void	AgoraAdmin::RightManager::RemoveChannelRight(IUser* user)
{
	// remove de la base tout les channelRights d'un user
	Configuration::GetConfiguration()->GetDatabase()->DeleteChannelRightUser(user->GetId());
	if (this->_userChannelRight.count(user) && this->_userChannelRight[user].size() == 1)
		delete this->_userChannelRight[user].begin()->second;
	this->_userChannelRight.erase(user);
}

const AgoraAdmin::IHostRight&			AgoraAdmin::RightManager::GetHostRight(IUser* user)
{
	if(this->_userHostRight.count(user))
		return *(this->_userHostRight[user]);
	IDatabase::DbResult* result = Configuration::GetConfiguration()->GetDatabase()->SelectHostRight(user->GetId());
	if (result->size() == 0)
	{
		//creer un nouveau hostright base sur celui par default
		delete result;
		Configuration::GetConfiguration()->GetDatabase()->CreateHostRightDefault(user->GetId());
		result = Configuration::GetConfiguration()->GetDatabase()->SelectHostRight(user->GetId());
	}
	std::vector<bool> vectorRight;
	vectorRight.push_back((*result->at(0))["canChangeLogin"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canChangePassword"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canChangeChannel"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canCreateChannel"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canDeleteChannel"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canMoveChannel"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canKickUser"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canBanUser"]->GetValueBool());
	vectorRight.push_back((*result->at(0))["canEditUser"]->GetValueBool());
	HostRight* right = new HostRight((*result->at(0))["id"]->GetValueInt(), vectorRight);
	delete result;
	this->_userHostRight[user] = right;
	return *right;
}

void						AgoraAdmin::RightManager::SetHostRight(IUser* user, const bool canChangeLogin, const bool canChangePassword, const bool canChangeChannel, const bool canCreateChannel, const bool canDeleteChannel, const bool canMoveChannel, const bool canKickUser, const bool canBanUser, const bool canEditUser)
{
	// modif map si donnee existante dans map, et la db en meme tps
	if(this->_userHostRight.count(user))
		this->_userHostRight[user]->SetHostRight(canChangeLogin, canChangePassword, canChangeChannel, canCreateChannel, canDeleteChannel, canMoveChannel, canKickUser, canBanUser, canEditUser);
	else
	{
		// sinon on modif seulement dans la base
		unsigned int id = Configuration::GetConfiguration()->GetDatabase()->SelectHostRightId(user->GetId());
		//ici on peut check si une erreur a ete emise, si c'est le cas on cree un right par default
		Configuration::GetConfiguration()->GetDatabase()->UpdateHostRight(id, canChangeLogin, canChangePassword, canChangeChannel, canCreateChannel, canDeleteChannel, canMoveChannel, canKickUser, canBanUser, canEditUser);
	}
}

void						AgoraAdmin::RightManager::RemoveHostRight(IUser* user)
{
	// remove de la base tout les channelRights d'un user
	Configuration::GetConfiguration()->GetDatabase()->DeleteHostRightUser(user->GetId());
	if (this->_userHostRight.count(user))
		delete this->_userHostRight[user];
	this->_userHostRight.erase(user);
}
